/**
 * 
 */
package com.wgo.bpot.server.util;



/**
 * Converts ejb-instances to domain-model-instances. Links/relations are 
 * converted to customized level (determined by parameter).
 * 
 * @author petterei  
 */
public class ServerModelConverter {

//	private static final transient Logger log = Logger.getLogger(ServerModelConverter.class);
//	
//	private static Map<Class<? extends Object>,Class<? extends Object>> modelToEjbTypeCache = new Hashtable<Class<? extends Object>,Class<? extends Object>>(10);	
//	private static Map<Class, Class<Persistent>> ejbToModelTypeCache = new Hashtable<Class, Class<Persistent>>();
//
//	/**
//	 * Converts an ejb-instance to a domain-model-instance with all relations 
//	 * intact. The objects referenced to is partial-instances.
//	 * 
//	 * @param ejbInstance The ejb-instance to be converted.
//	 * @param triggerRegistry 
//	 * @return The converted domain-model-instance.
//	 */
//	@SuppressWarnings("unchecked")
//	public static Object convertToDomainModel(Persistent ejbInstance, int levels, Map<String, Object> cache, TriggerRegistry triggerRegistry) {
//		if (null == ejbInstance || 0 > levels) {
//			return null;
//		}
//		String cacheIdentifier = ejbInstance.getClass().getSimpleName()+ejbInstance.getDbId();
//		if (cache.containsKey(cacheIdentifier)) {
//			return cache.get(cacheIdentifier);
//		}
//		levels--;
//		Class implClass = loadModelClass(ejbInstance.getClass());
//		Persistent domainObject;
//		try {
//			domainObject = (Persistent)implClass.newInstance();
//		} catch (Exception e) {
//			String message = "Could not create DomainModel instance of type: " + implClass.getSimpleName() + " Source-type was: " + ejbInstance.getClass().getSimpleName();
//			log.error(message, e);
//			throw new DatabaseException(message, e);
//		}
//		cache.put(cacheIdentifier, domainObject);
//		Class[] interfaces = implClass.getInterfaces();
//		Map<String,Class> dispatchedMethods = new Hashtable<String,Class>();
//		for (Class clazz : interfaces) {
//			for (Method method : clazz.getMethods()) {
//				MethodNamingConvention methodType = MethodNamingConvention.getMethodType(method);
//				if( null == methodType) // for greater flexibility regarding business methods (transient)
//					continue;
//				Method realGetter = methodType.retriveGetterMethod(implClass, method);
//				if( null == realGetter) // for greater flexibility regarding business methods (transient)
//					continue;
//				Class methodReturnType = realGetter.getReturnType();
//				Class existingValue = dispatchedMethods.put(realGetter.getName(), methodReturnType);
//				if (null == existingValue || existingValue != methodReturnType) { // only set attributes once..
//					Method realSetter = methodType.retriveSetterMethod(implClass, method);
//					if( null == realSetter)
//						continue;
//					Object ejbValue = ReflectionHelper.<Persistent>invokeMethod(ejbInstance, realGetter);
//					Object argument = null;
//					if (MethodNamingConvention.isActualLinkToConcept(realGetter)) {
//						triggerRetrieve(triggerRegistry, ejbValue);
//						argument = convertToDomainModel((Persistent)ejbValue, levels, cache,triggerRegistry);
//					} else if (MethodNamingConvention.isActualLinkToConcepts(realGetter)) {
//						Collection domainModelCollection = null;
//						if (Set.class.isAssignableFrom(methodReturnType)) {
//							domainModelCollection = new HashSet();
//						} else if (List.class.isAssignableFrom(methodReturnType)) {
//							domainModelCollection = new ArrayList();
//						} else {
//							String message = "Type " + ejbInstance.getClass().getSimpleName() + " has getter which returns collection of unknown type: " + methodReturnType.getSimpleName() + " This collections is ignored in the conversion.";
//							log.warn(message);
//							continue;
//						}
//						for (Persistent ejbRelationInstance : (Collection<Persistent>)ejbValue) {
//							triggerRetrieve(triggerRegistry, ejbRelationInstance);
//							Object linkResult = ServerModelConverter.convertToDomainModel(ejbRelationInstance, levels, cache,triggerRegistry);
//							if (null != linkResult) {
//								domainModelCollection.add(linkResult);
//							}
//						}
//						argument = domainModelCollection;
//					} else {
//						argument = ejbValue;
//					}
//					
////					log.info("Conversion, method dispatched: " + method.getName() + ", declaring interface: " + clazz.getSimpleName() + ", realGetter: " + realGetter.getName()+ ", realSetter: " + realSetter.getName());
//					ReflectionHelper.<Persistent>invokeMethod(domainObject, realSetter, argument);
//				}
//			}
//		}
//		return domainObject;
//	}
//
//	private static void triggerRetrieve(TriggerRegistry triggerRegistry, Object ejbValue) {
//		if (null != triggerRegistry) {
//			triggerRegistry.invokeBefore(CrudOperation.RETRIEVE,ejbValue);
//			triggerRegistry.invokeAfter(CrudOperation.RETRIEVE,ejbValue);
//		}
//	}
//	
//	@SuppressWarnings("unchecked")
//	public static <T extends Object> Class<T> loadServerClass(Class<T> domainModelInterface) {
//		if (modelToEjbTypeCache.containsKey(domainModelInterface)) {
//			return (Class<T>)modelToEjbTypeCache.get(domainModelInterface);
//		}
//		Class<T> implClass = DomainModelTypeNamingConvention.loadServerClass(domainModelInterface);//, ServerModelNamingConvention.MODEL_IMPL_PACKAGE, ServerModelNamingConvention.MODEL_TYPE_SUFFIX);
//		modelToEjbTypeCache.put(domainModelInterface,implClass);
//		return implClass;
//	}
//	
//	@SuppressWarnings("unchecked")
//	public static Class<Persistent> loadModelClass(Class ejbClass) {
//		if (ejbToModelTypeCache.containsKey(ejbClass)) {
//			return ejbToModelTypeCache.get(ejbClass);
//		}
//		Class apiClass = DomainModelTypeNamingConvention.getImplClassFromEjbClass(ejbClass);
//		ejbToModelTypeCache.put(ejbClass,apiClass);
//		return apiClass;
//	}
}
